//
//  CrashInfoCollectionObject.m
//  cman
//
//  Created by 王建华 on 2024/6/18.
//

#import "CrashInfoCollectionObject.h"

@implementation CrashInfoCollectionObject

void SignalHandler(int signal) {
   // 这里可以添加信号处理的代码，例如保存信号相关的崩溃信息
   raise(signal); // 重新抛出信号，让系统处理信号
}

void UncaughtExceptionHandler(NSException *exception) {
    // 获取崩溃的线程
    NSThread *crashedThread = [NSThread currentThread];
    // 获取崩溃的线程调用栈
    NSArray *callStack = [exception callStackSymbols];

    // 奔溃日志存放路径
    NSString *crashLogPath = [CrashInfoCollectionObject getCrashFilePath];
    
    // 4. 读取crash.log文件的内容（如果不存在则创建一个空字符串）
    NSString *existingContent = [NSString stringWithContentsOfFile:crashLogPath encoding:NSUTF8StringEncoding error:nil];
    if (!existingContent) {
        existingContent = @""; // 文件不存在，使用空字符串
    }
    // 5. 将新内容追加到旧内容之后
    NSString *updatedContent = [existingContent stringByAppendingString:[NSString stringWithFormat:@"\r\n\r\n\n\n%@-----------\r\n\r\nUncaught exception: %@\r\nThread: %@\r\nName:\r\n%@\r\nCall stack:\r\n%@",[NSDate date], exception, crashedThread, exception.name, [callStack componentsJoinedByString:@"\r\n"]]];

    // 6. 将更新后的内容写回到crash.log文件
    BOOL success = [updatedContent writeToFile:crashLogPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    if (!success) {
        NSLog(@"Error writing to crash.log file");
    }
}


+ (void)setUncaughtException {
    // 设置未捕获异常的处理器
    NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);

    // 注册其他信号处理器
    signal(SIGABRT, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGFPE, SignalHandler);
    signal(SIGBUS, SignalHandler);
    signal(SIGTERM, SignalHandler);

    // ... 正常的应用启动和运行代码
}

+ (NSString *)getCrashFilePath {
    
    // 1. 获取Documents目录的路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    // 2. 构建crashinfo子目录的路径
    NSString *crashInfoDirectory = [documentsDirectory stringByAppendingPathComponent:@"crashinfo"];
    // 检查crashinfo目录是否存在，如果不存在则创建它
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:crashInfoDirectory]) {
        NSError *error = nil;
        BOOL success = [fileManager createDirectoryAtPath:crashInfoDirectory withIntermediateDirectories:YES attributes:nil error:&error];
        if (!success) {
            NSLog(@"Error creating crashinfo directory: %@", error);
            // 处理错误...
        }
    }
    // 3. 构建完整的crash.log文件路径
    NSString *crashLogPath = [crashInfoDirectory stringByAppendingPathComponent:@"crash.log"];
    
    return crashLogPath;
}

+ (void)presentFromViewController:(UIViewController *)superViewController {
    
    NSString *logPath = [CrashInfoCollectionObject getCrashFilePath];
    if ( ![[NSFileManager defaultManager] fileExistsAtPath:logPath ] ) {
        NSLog(@"log file is not exists");
        return;
    }
    
    NSURL *logURL = [NSURL fileURLWithPath:logPath];
    UIDocumentPickerViewController *documentPickerViewController = [[UIDocumentPickerViewController alloc] initWithURL:logURL inMode:UIDocumentPickerModeExportToService];
    [superViewController presentViewController:documentPickerViewController animated:YES completion:nil];
}

@end
